package com.ruoyi.examination.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.github.pagehelper.PageInfo;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.examination.domain.QuestionGroup;
import com.ruoyi.examination.domain.QuestionGroupRelation;
import com.ruoyi.examination.domain.QuestionOption;
import com.ruoyi.examination.dto.QuestionImportDto;
import com.ruoyi.examination.mapper.QuestionGroupMapper;
import com.ruoyi.examination.mapper.QuestionGroupRelationMapper;
import com.ruoyi.examination.mapper.QuestionOptionMapper;
import com.ruoyi.examination.util.SnowflakeIdUtils;
import com.ruoyi.examination.vo.QuestionSelectVo;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.examination.mapper.QuestionMapper;
import com.ruoyi.examination.domain.Question;
import com.ruoyi.examination.service.IQuestionService;

import static com.ruoyi.common.core.utils.PageUtils.startPage;

/**
 * 试题管理Service业务层处理
 *
 * @author hcc
 * @date 2025-10-21
 */
@Service
public class QuestionServiceImpl implements IQuestionService {
    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private QuestionOptionMapper questionOptionMapper;

    @Autowired
    private QuestionGroupMapper questionGroupMapper;

    @Autowired
    private QuestionGroupRelationMapper questionGroupRelationMapper;

    /**
     * 查询试题管理
     *
     * @param questionId 试题管理主键
     * @return 试题管理
     */
    @Override
    public Question selectQuestionByQuestionId(String questionId) {
        Question question = questionMapper.selectQuestionByQuestionId(questionId);
        // 查询选项内容通过试题id
        List<QuestionOption> questionOptionList = questionOptionMapper.selectQuestionOptionByQuestionId(question.getQuestionId());
        question.setQuestionOptionList(questionOptionList);
        return question;
    }

    /**
     * 查询试题管理列表
     *
     * @param question 试题管理
     * @return 试题管理
     */
    @Override
    public List<Question> selectQuestionList(Question question) {
        return questionMapper.selectQuestionList(question);
    }

    /**
     * 新增试题管理
     *
     * @param question 试题管理
     * @return 结果
     */
    @Override
    public int insertQuestion(Question question) {
        question.setQuestionId(String.valueOf(new SnowflakeIdUtils(5, 8).nextId()));
        if (question.getQuestionOptionList() != null && question.getQuestionOptionList().size() > 0) {
            for (QuestionOption questionOption : question.getQuestionOptionList()) {
                questionOption.setQuestionId(question.getQuestionId());
                questionOption.setOptionId(String.valueOf(new SnowflakeIdUtils(5, 8).nextId()));
                questionOption.setCreateTime(DateUtils.getNowDate());
                questionOption.setCreateBy(SecurityUtils.getUsername());
                questionOption.setDelFlag("0");
                questionOptionMapper.insertQuestionOption(questionOption);
            }
        }
        question.setDelFlag("0");
        question.setCreateBy(SecurityUtils.getUsername());
        question.setCreateTime(DateUtils.getNowDate());
        return questionMapper.insertQuestion(question);
    }

    /**
     * 修改试题管理
     *
     * @param question 试题管理
     * @return 结果
     */
    @Override
    public int updateQuestion(Question question) {
        if (question.getQuestionOptionList() != null && question.getQuestionOptionList().size() > 0) {
            for (QuestionOption questionOption : question.getQuestionOptionList()) {
                questionOptionMapper.deleteQuestionOptionByOptionId(questionOption.getOptionId());
                questionOptionMapper.insertQuestionOption(questionOption);
            }
        }
        if (question.getQuestionGroupIds() != null && question.getQuestionGroupIds().length > 0) {
            StringJoiner questionGroupNames = new StringJoiner(";");
            for (String questionGroupId : question.getQuestionGroupIds()) {
                QuestionGroup questionGroup = questionGroupMapper.selectQuestionGroupByGroupId(questionGroupId);
                if (StringUtils.isNotNull(questionGroup)) {
                    questionGroupNames.add(questionGroup.getGroupName());
                }
            }
            question.setRelateGroupName(questionGroupNames.toString());
        }
        question.setUpdateTime(DateUtils.getNowDate());
        return questionMapper.updateQuestion(question);
    }

    /**
     * 批量删除试题管理
     *
     * @param questionIds 需要删除的试题管理主键
     * @return 结果
     */
    @Override
    public int deleteQuestionByQuestionIds(String[] questionIds) {
        return questionMapper.deleteQuestionByQuestionIds(questionIds);
    }

    /**
     * 删除试题管理信息
     *
     * @param questionId 试题管理主键
     * @return 结果
     */
    @Override
    public int deleteQuestionByQuestionId(String questionId) {
        return questionMapper.deleteQuestionByQuestionId(questionId);
    }

    /**
     * 查询试题管理列表
     */
    @Override
    public List<Question> getList(QuestionSelectVo questionSelectVo) {
        if (StringUtils.isNotEmpty(questionSelectVo.getRelateGroupId())) {
            // 获取该分组关联的所有问题关系
            List<QuestionGroupRelation> questionGroupRelationList = questionGroupRelationMapper.selectQuestionGroupRelationByGroupId(questionSelectVo.getRelateGroupId());
            // 提取所有需要排除的questionId
            List<String> excludeQuestionIds = questionGroupRelationList.stream()
                    .map(QuestionGroupRelation::getQuestionId)
                    .collect(Collectors.toList());
            // 从questionList中移除id匹配的记录
            questionSelectVo.setQuestionIds(excludeQuestionIds);
        }
        startPage(questionSelectVo.getPageNum(), questionSelectVo.getPageSize());
        List<Question> questionList = questionMapper.getList(questionSelectVo);
        return questionList;
    }

    /**
     * 批量逻辑删除试题管理
     */
    @Override
    public int removeQuestion(String[] questionIds) {
        int i = questionMapper.removeQuestionByQuestionIds(questionIds);
        // 批量删除选项根据试题id
        questionOptionMapper.deleteQuestionOptionByQuestionIds(questionIds);
        // 批量删除题组根据试题id
        questionGroupRelationMapper.deleteQuestionGroupRelationByQuestionGroupIds(questionIds);
        return i;
    }

    /**
     * 导入试题管理
     */
    @Override
    public String importQuestion(List<QuestionImportDto> questionList, boolean updateSupport, String operName) {
        if (questionList == null || questionList.isEmpty()) {
            throw new ServiceException("导入试题信息不能为空");
        }

        // 复用雪花ID生成器（避免重复创建对象）
        SnowflakeIdUtils idGenerator = new SnowflakeIdUtils(5, 8);
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        List<String> errorList = new ArrayList<>(); // 记录每行错误信息

        for (int i = 0; i < questionList.size(); i++) {
            QuestionImportDto dto = questionList.get(i);
            int rowNum = i + 2; // 行号从2开始（第1行为表头）
            try {
                // 1. 数据校验（核心：过滤无效数据）
                String validateMsg = validateQuestion(dto, rowNum);
                if (validateMsg != null) {
                    failureNum++;
                    errorList.add(validateMsg);
                    continue;
                }

                // 转换题型文本为code（如"单选"→"1"）
                String questionType = TYPE_MAP.get(dto.getQuestionType());
                // 判断试题是否已存在（通过题干+题型唯一标识）
                Question existQuestion = questionMapper.selectQuestionByCondition(dto.getQuestionName(), questionType);
                if (existQuestion != null) {
                    // 已存在：根据updateSupport判断是否更新
//                    if (updateSupport) {
                        // 更新试题基本信息
                        Question updateQuestion = new Question();
                        BeanUtils.copyProperties(dto, updateQuestion);
                        updateQuestion.setQuestionId(existQuestion.getQuestionId()); // 关键：用已有ID更新
                        updateQuestion.setUpdateBy(operName);
                        updateQuestion.setUpdateTime(DateUtils.getNowDate());
                        questionMapper.updateQuestion(updateQuestion);
                        // 先删除旧选项，再插入新选项（保证选项与最新数据一致）
                        questionOptionMapper.deleteQuestionOptionByQuestionId(existQuestion.getQuestionId());
                        insertOptions(dto, existQuestion.getQuestionId(), questionType, idGenerator);
                        successNum++;
                        successMsg.append(String.format("第%d行更新成功；", rowNum));
//                    } else {
//                        // 不更新：记录为失败（已存在）
//                        failureNum++;
//                        errorList.add(String.format("第%d行：试题已存在（未更新）", rowNum));
//                    }
                } else {
                    //  不存在：新增试题
                    Question newQuestion = new Question();
                    BeanUtils.copyProperties(dto, newQuestion);
                    String questionId = String.valueOf(idGenerator.nextId()); // 生成唯一ID
                    newQuestion.setQuestionId(questionId);
                    newQuestion.setQuestionType(questionType); // 设置转换后的题型code
                    newQuestion.setCreateBy(operName);
                    newQuestion.setCreateTime(DateUtils.getNowDate());
                    newQuestion.setUpdateBy(operName);
                    newQuestion.setUpdateTime(DateUtils.getNowDate());
                    newQuestion.setDelFlag("0"); // 默认未删除
                    questionMapper.insertQuestion(newQuestion);

                    // 插入选项（仅单选/多选需要）
                    insertOptions(dto, questionId, questionType, idGenerator);

                    successNum++;
                    successMsg.append(String.format("第%d行导入成功；", rowNum));
                }
            } catch (Exception e) {
                // 捕获异常：记录错误，继续处理后续数据
                failureNum++;
                String errorMsg = String.format("第%d行导入失败：%s", rowNum, e.getMessage());
                errorList.add(errorMsg);
            }
        }

        // 构建最终返回消息
        if (failureNum > 0) {
            failureMsg.append("导入失败：").append(String.join("；", errorList));
            // 失败时仍返回成功数（部分成功场景）
            return String.format("总导入：%d条，成功：%d条，失败：%d条。失败原因：%s",
                    questionList.size(), successNum, failureNum, failureMsg);
        } else {
            successMsg.append("全部导入成功！");
            return String.format("总导入：%d条，全部成功。", questionList.size());
        }
    }

    /**
     * 试题关联分组
     */
    @Override
    public int associationGroup(Question question) {
        int i = 0;
        if (StringUtils.isNotEmpty(question.getQuestionId()) && StringUtils.isNotEmpty(question.getQuestionGroupIds())) {
            // 获取关联分组信息通过questionId
            List<QuestionGroupRelation> questionGroupRelationList = questionGroupRelationMapper.selectQuestionGroupRelationByQuestionId(question.getQuestionId());
            // 获取已关联分组ID
            List<String> collect = questionGroupRelationList.stream().map(QuestionGroupRelation::getGroupId).collect(Collectors.toList());
            ArrayList<String> questionGroupIdsList = new ArrayList<>(Arrays.asList(question.getQuestionGroupIds()));
            // 移除已关联的分组
            questionGroupIdsList.removeIf(groupId -> collect.contains(groupId));
            for (String groupId : questionGroupIdsList) {
                QuestionGroupRelation questionGroupRelation = new QuestionGroupRelation();
                questionGroupRelation.setQuestionId(question.getQuestionId());
                questionGroupRelation.setGroupId(groupId);
                questionGroupRelation.setQuestionGroupId(String.valueOf(new SnowflakeIdUtils(5, 8).nextId()));
                questionGroupRelationMapper.insertQuestionGroupRelation(questionGroupRelation);
            }
            Question questionDb = questionMapper.selectQuestionByQuestionId(question.getQuestionId());
            if (StringUtils.isNotNull(questionDb)) {
                StringJoiner joinerName = new StringJoiner(";");
                StringJoiner joinerIds = new StringJoiner(";");
                if (StringUtils.isNotEmpty(questionDb.getRelateGroupId())) {
                    joinerIds.add(questionDb.getRelateGroupId());
                }
                // 仅添加非空的原始关联名称
                if (StringUtils.isNotEmpty(questionDb.getRelateGroupName())) {
                    joinerName.add(questionDb.getRelateGroupName());
                }
                List<QuestionGroup> questionGroups = questionGroupMapper.selectQuestionGroupByGroupIds(questionGroupIdsList);
                for (QuestionGroup questionGroup : questionGroups) {
                    joinerName.add(questionGroup.getGroupName());
                    joinerIds.add(questionGroup.getGroupId());
                }
                questionDb.setRelateGroupName(joinerName.toString());
                questionDb.setRelateGroupId(joinerIds.toString());
                questionDb.setRelateStatus("1");
                questionDb.setUpdateTime(DateUtils.getNowDate());
                questionDb.setUpdateBy(SecurityUtils.getUsername());
                i = questionMapper.updateQuestion(questionDb);
            }
        }
        return i;
    }

    /**
     * 查看题组已关联题目
     */
    @Override
    public List<Question> viewQuestion(QuestionSelectVo questionSelectVo) {
        // 获取该分组关联的所有问题关系
        List<QuestionGroupRelation> questionGroupRelationList = questionGroupRelationMapper.selectQuestionGroupRelationByGroupId(questionSelectVo.getRelateGroupId());

        List<Question> questionList = new ArrayList<>();
        // 提取所有questionId
        if (CollectionUtils.isNotEmpty(questionGroupRelationList)){
            List<String> relatedQuestionIds = questionGroupRelationList.stream()
                    .map(QuestionGroupRelation::getQuestionId)
                    .collect(Collectors.toList());
            questionSelectVo.setQuestionIds(relatedQuestionIds);
            startPage(questionSelectVo.getPageNum(), questionSelectVo.getPageSize());
            questionList = questionMapper.viewQuestion(questionSelectVo);
        }
        return questionList;
    }

    /**
     * 校验试题数据合法性
     *
     * @param dto    导入DTO
     * @param rowNum 行号（用于错误提示）
     * @return 错误信息（null表示校验通过）
     */
    private String validateQuestion(QuestionImportDto dto, int rowNum) {
        // 1. 必传项校验
        if (StringUtils.isBlank(dto.getQuestionName())) {
            return String.format("第%d行：题干不能为空", rowNum);
        }
        if (StringUtils.isBlank(dto.getQuestionType())) {
            return String.format("第%d行：题型不能为空（必须为单选/多选/判断）", rowNum);
        }
        if (StringUtils.isBlank(dto.getAnswer())) {
            return String.format("第%d行：答案不能为空", rowNum);
        }
        // 2. 题型合法性校验
        if (!TYPE_MAP.containsKey(dto.getQuestionType())) {
            return String.format("第%d行：题型无效（必须为单选/多选/判断）", rowNum);
        }
        String questionType = TYPE_MAP.get(dto.getQuestionType());

        // 3. 选项校验（仅单选/多选）
        if ("1".equals(questionType) || "2".equals(questionType)) {
            // 至少有一个有效选项（A-D中至少一个非空）
            boolean hasValidOption = StringUtils.isNotBlank(dto.getOptionA())
                    || StringUtils.isNotBlank(dto.getOptionB())
                    || StringUtils.isNotBlank(dto.getOptionC())
                    || StringUtils.isNotBlank(dto.getOptionD());
            if (!hasValidOption) {
                return String.format("第%d行：单选/多选题必须填写至少一个选项（A-D）", rowNum);
            }
            // 答案格式校验（必须是A/B/C/D的组合，多选用逗号分隔）
            String[] answerCodes = dto.getAnswer().split(",");
            for (String code : answerCodes) {
                if (!"A".equals(code) && !"B".equals(code) && !"C".equals(code) && !"D".equals(code)) {
                    return String.format("第%d行：答案包含无效选项（%s），只能是A/B/C/D", rowNum, code);
                }
            }
        }
        // 4. 判断题答案校验
        if ("3".equals(questionType)) {
            if (!"正确".equals(dto.getAnswer()) && !"错误".equals(dto.getAnswer())) {
                return String.format("第%d行：判断题答案必须为“正确”或“错误”", rowNum);
            }
        }
        return null; // 校验通过
    }

    /**
     * 插入选项（仅处理有内容的选项，且仅单选/多选需要）
     *
     * @param dto          导入DTO
     * @param questionId   试题ID
     * @param questionType 题型code（1/2/3）
     * @param idGenerator  雪花ID生成器
     */
    private void insertOptions(QuestionImportDto dto, String questionId, String questionType, SnowflakeIdUtils idGenerator) {
        // 判断题不需要选项，直接返回
        if ("3".equals(questionType)) {
            return;
        }
        // 选项A：仅当内容非空时插入
        if (StringUtils.isNotBlank(dto.getOptionA())) {
            QuestionOption optionA = buildOption(questionId, "A", dto.getOptionA(), idGenerator);
            questionOptionMapper.insertQuestionOption(optionA);
        }
        // 选项B：仅当内容非空时插入
        if (StringUtils.isNotBlank(dto.getOptionB())) {
            QuestionOption optionB = buildOption(questionId, "B", dto.getOptionB(), idGenerator);
            questionOptionMapper.insertQuestionOption(optionB);
        }
        // 选项C：仅当内容非空时插入
        if (StringUtils.isNotBlank(dto.getOptionC())) {
            QuestionOption optionC = buildOption(questionId, "C", dto.getOptionC(), idGenerator);
            questionOptionMapper.insertQuestionOption(optionC);
        }
        // 选项D：仅当内容非空时插入
        if (StringUtils.isNotBlank(dto.getOptionD())) {
            QuestionOption optionD = buildOption(questionId, "D", dto.getOptionD(), idGenerator);
            questionOptionMapper.insertQuestionOption(optionD);
        }
    }

    /**
     * 构建单个选项对象
     */
    private QuestionOption buildOption(String questionId, String optionName, String content, SnowflakeIdUtils idGenerator) {
        QuestionOption option = new QuestionOption();
        option.setOptionId(String.valueOf(idGenerator.nextId()));
        option.setQuestionId(questionId);
        option.setOptionName(optionName);
        option.setOptionContent(content);
        option.setDelFlag("0"); // 默认未删除
        return option;
    }

    // 题型映射：Excel文本 -> 数据库code
    private static final Map<String, String> TYPE_MAP = new HashMap<>();

    static {
        TYPE_MAP.put("单选", "1");
        TYPE_MAP.put("多选", "2");
        TYPE_MAP.put("判断", "3");
    }
}
